package io.gitee.welson.sensitive.strategy.impl;

import io.gitee.welson.sensitive.annotation.SensitiveStrategyComponent;
import io.gitee.welson.sensitive.condition.ConditionEvaluator;
import io.gitee.welson.sensitive.strategy.SensitiveStrategy;
import io.gitee.welson.sensitive.util.SensitiveUtil;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 关键字脱敏策略
 * 规则：将字段中包含的关键字替换为*号
 * 用法示例：
 * 1. 直接指定关键字：
 * @SensitiveField(
 *     strategy = KeywordSensitiveStrategy.class,
 *     params = {"敏感词1", "敏感词2", "敏感词3"}
 * )
 * 2. 使用SpEL表达式：
 * @SensitiveField(
 *     strategy = KeywordSensitiveStrategy.class,
 *     params = {"@keywordService.getKeywords()"}
 * )
 *
 * @author welson
 */
@SensitiveStrategyComponent
public class KeywordSensitiveStrategy implements SensitiveStrategy {

    private final ConditionEvaluator conditionEvaluator;

    public KeywordSensitiveStrategy(ConditionEvaluator conditionEvaluator) {
        this.conditionEvaluator = conditionEvaluator;
    }

    @Override
    public String desensitize(String value, String... params) {
        if (!StringUtils.hasText(value) || params == null || params.length == 0) {
            return value;
        }

        try {
            // 获取关键字列表
            Collection<String> keywords;

            // 如果只有一个参数，尝试作为表达式解析
            if (params.length == 1 && params[0].startsWith("@")) {
                keywords = getKeywordsFromExpression(params[0]);
            } else {
                // 否则直接使用所有参数作为关键字
                keywords = Arrays.asList(params);
            }

            if (keywords == null || keywords.isEmpty()) {
                return value;
            }

            // 构建正则表达式
            String regex = String.join("|",
                    keywords.stream()
                            .filter(StringUtils::hasText)
                            .map(Pattern::quote)
                            .toArray(String[]::new)
            );

            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(value);
            StringBuffer result = new StringBuffer();

            while (matcher.find()) {
                String matched = matcher.group();
                String masked = SensitiveUtil.createMask(matched.length());
                matcher.appendReplacement(result, Matcher.quoteReplacement(masked));
            }
            matcher.appendTail(result);

            return result.toString();
        } catch (Exception e) {
            return value;
        }
    }

    @SuppressWarnings("unchecked")
    private Collection<String> getKeywordsFromExpression(String expression) {
        try {
            Object result = conditionEvaluator.evaluateExpression(expression);

            if (result instanceof Collection) {
                return (Collection<String>) result;
            } else if (result instanceof String[]) {
                return Arrays.asList((String[]) result);
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }
}